import sys
from PyQt5.QtCore import Qt, pyqtSignal, QThread
from PyQt5.QtWidgets import QApplication, QMainWindow, QLabel, QLineEdit, QPushButton, QVBoxLayout, QWidget, QListWidget, QFileDialog, QListWidgetItem, QProgressBar, QHBoxLayout, QSizePolicy
from PyQt5.QtGui import QIcon
from yandex_oauth import YandexOAuth
from yandex_client import YandexMusicClient
from downloader import Downloader


class MyApplication(QMainWindow):

    got_token = pyqtSignal(str)

    def __init__(self):
        super().__init__()
        self.setWindowTitle("Yandex Music Playlists Downloader")
        self.resize(400, 400)
        self.setWindowIcon(QIcon("icon.png"))

        # Widgets for token retrieval
        self.token_label = QLabel("Токен:")
        self.token_edit = QLineEdit()
        self.token_edit.editingFinished.connect(lambda: self.save_token() and self.load_token())
        self.get_token_button = QPushButton("Получить токен")
        self.get_token_button.clicked.connect(lambda: YandexOAuth(self))
        self.got_token.connect(self.got_token_function)

        # Widgets for playlist selection and download
        self.playlists_label = QLabel("Плейлисты:")
        self.playlists_list = QListWidget()
        self.playlists_list.setSelectionMode(QListWidget.MultiSelection)
        self.load_playlists_button = QPushButton("Загрузить плейлисты")
        self.load_playlists_button.clicked.connect(self.load_playlists)

        # Widgets for specifying the download path
        self.path_label = QLabel("Путь для загрузки:")
        self.path_edit = QLineEdit()
        self.path_edit.editingFinished.connect(lambda: self.save_path() and self.load_path())
        self.browse_button = QPushButton()
        self.browse_button.setIcon(QIcon.fromTheme("folder-open"))
        self.browse_button.clicked.connect(self.select_path)

        # Button to start the download process
        self.download_button = QPushButton("Загрузить")
        self.download_button.clicked.connect(self.download_playlists)

        # Progress bar to show the download progress
        self.progress_bar = QProgressBar()
        self.progress_bar.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)

        # Create the main layout and set it as the central widget
        main_widget = QWidget(self)
        self.setCentralWidget(main_widget)
        layout = QVBoxLayout(main_widget)

        # Arrange the widgets in the main layout
        layout.addWidget(self.token_label)
        layout.addWidget(self.token_edit)
        layout.addWidget(self.get_token_button)

        playlists_layout = QHBoxLayout()
        playlists_layout.addWidget(self.playlists_label)
        playlists_layout.addWidget(self.load_playlists_button)
        layout.addLayout(playlists_layout)

        layout.addWidget(self.playlists_list)

        path_layout = QHBoxLayout()
        path_layout.addWidget(self.path_edit)
        path_layout.addWidget(self.browse_button)
        layout.addLayout(path_layout)

        layout.addWidget(self.download_button)
        layout.addWidget(self.progress_bar)

        # Initialize variables to store token and playlists
        self.token = ""
        self.playlists = []
        self.music_client = None

        # Load previously saved token and path
        self.load_token()
        self.load_path()

        # Show the application window
        self.show()

    # Method to select a folder for download
    def select_path(self):
        options = QFileDialog.Options()
        path = QFileDialog.getExistingDirectory(self, "Выбрать папку", options=options)
        if path:
            self.path_edit.setText(path)
            self.save_path()

    # Method to save the selected download path to a file
    def save_path(self):
        path = self.path_edit.text()
        if not path:
            return

        with open(".path", "w", encoding="utf-8") as file_:
            file_.write(path)

        return True

    # Method to load the last selected download path from the file
    def load_path(self):
        try:
            with open(".path", "r", encoding="utf-8") as file_:
                path = file_.read().strip()
                self.path_edit.setText(path)
                return True
        except FileNotFoundError:
            return False

    # Method to get the selected playlists from the list widget
    def get_selected_playlists(self):
        selected_playlists = []
        for index in range(self.playlists_list.count()):
            item = self.playlists_list.item(index)
            if item.checkState() == Qt.Checked:
                selected_playlists.append(item)
        return selected_playlists

    # Signal handler for when the Yandex Music token is received
    def got_token_function(self, token):
        print("Yandex Music token:", token)
        self.token = token
        self.token_edit.setText(self.token)
        self.save_token()

        self.music_client = YandexMusicClient(token=self.token)

    # Method to save the Yandex Music token to a file
    def save_token(self):
        self.token = self.token_edit.text()

        if not self.token:
            return False

        with open(".token", "w", encoding="utf-8") as file_:
            file_.write(self.token)

        return True

    # Method to load the last saved Yandex Music token from a file
    def load_token(self):
        try:
            with open(".token", "r", encoding="utf-8") as file_:
                self.token = file_.read().strip()
                self.token_edit.setText(self.token)

                self.music_client = YandexMusicClient(token=self.token)

                return True

        except FileNotFoundError:
            return False

    # Method to load the playlists from the Yandex Music client and populate the list widget
    def load_playlists(self):
        self.playlists = self.music_client.get_playlists()

        self.playlists_list.clear()

        for playlist in self.playlists:
            title = playlist["title"]

            item = QListWidgetItem(title)
            item.setFlags(item.flags() | Qt.ItemIsUserCheckable)
            item.setCheckState(Qt.Unchecked)
            self.playlists_list.addItem(item)

    # Method to start the playlist download process using a separate thread
    def download_playlists(self):
        selected_playlists = self.get_selected_playlists()
        selected_playlists_indexes = [self.playlists_list.row(playlist) for playlist in selected_playlists]
        selected_playlists = [self.playlists[index] for index in selected_playlists_indexes]

        save_path = self.path_edit.text()
        if save_path.endswith("/") or save_path.endswith("\\"):
            save_path = save_path[:-1]

        if not selected_playlists or not save_path:
            return

        self.thread = QThread()
        self.downloader = Downloader(self, selected_playlists, save_path)

        self.downloader.moveToThread(self.thread)

        self.thread.started.connect(self.downloader.run)
        self.thread.finished.connect(self.thread.deleteLater)
        self.downloader.finished.connect(self.thread.quit)
        self.downloader.finished.connect(self.downloader.deleteLater)

        self.thread.start()

        self.download_button.setEnabled(False)
        self.thread.finished.connect(lambda: self.download_button.setEnabled(True))


if __name__ == "__main__":
    app = QApplication(sys.argv)
    window = MyApplication()
    sys.exit(app.exec_())
